package com.sc.nft.controller;


import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.sc.nft.annotation.UserLogin;
import com.sc.nft.controller.request.*;
import com.sc.nft.dao.UserEquityPropsDao;
import com.sc.nft.entity.UserInfo;
import com.sc.nft.entity.congestive.GiftCT;
import com.sc.nft.entity.dto.AddressUserInfoDTO;
import com.sc.nft.entity.dto.GiftDTO;
import com.sc.nft.entity.dto.IncrementalLossCalculationDTO;
import com.sc.nft.entity.vo.*;
import com.sc.nft.entity.vo.secondEquityProp.EquityPropsLastConsignDetailsVO;
import com.sc.nft.entity.vo.secondEquityProp.MyConsignEquityPropsPageVO;
import com.sc.nft.entity.vo.secondEquityProp.RealAmountVO;
import com.sc.nft.enums.RedisKeyEnum;
import com.sc.nft.exception.GlobalRunTimeException;
import com.sc.nft.exception.GlobalException;
import com.sc.nft.exception.GlobalRunTimeException;
import com.sc.nft.pool.UserPool;
import com.sc.nft.service.SecondEquityPropsService;
import com.sc.nft.service.UserEquityPropsService;
import com.sc.nft.sup.ErrorCode;
import com.sc.nft.sup.PageRequest;
import com.sc.nft.sup.PageResult;
import com.sc.nft.sup.Result;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.redisson.Redisson;
import org.redisson.api.RLock;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.validation.Valid;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Lock;

@Slf4j
@RequiredArgsConstructor
@RestController
@RequestMapping("/equityProps")
@Api(tags = "权益道具")
public class EquityPropsController {

    private final UserEquityPropsService userEquityPropsService;
    private final SecondEquityPropsService secondEquityPropsService;
    private final Redisson redisson;



    @ApiOperation(value = "我的权益道具获取记录(任务中心-星球账单-权益道具-收入明细)", notes = "星球账单-权益道具", httpMethod = "POST", produces = MediaType.APPLICATION_JSON_VALUE)
    @PostMapping(value = "/getPageEquityPropsLog", produces = MediaType.APPLICATION_JSON_VALUE)
    @UserLogin
    public PageResult<PageEquityPropsLogVO> getPageEquityPropsLog(@Valid @RequestBody PageEquityPropsLogRequest request) {
        return PageResult.success(userEquityPropsService.getPageEquityPropsLog(UserPool.getUser(),request.getIsConsume(), request.getPageNo(), request.getPageSize()));
    }

    @ApiOperation(value = "我的权益道具(任务中心-我的奖励)", notes = "我的权益道具(任务中心-我的奖励)", httpMethod = "POST", produces = MediaType.APPLICATION_JSON_VALUE)
    @PostMapping(value = "/getPageUserEquityProps", produces = MediaType.APPLICATION_JSON_VALUE)
    @UserLogin
    public PageResult<PageUserEquityPropsVO> getPageUserEquityProps(@Valid @RequestBody PageUserEquityProps request) {
        return PageResult.success(userEquityPropsService.getPageUserEquityProps(UserPool.getUser(),request.getIsExpired(), request.getPageNo(), request.getPageSize()));
    }

    @ApiOperation(value = "我的权益道具（我的）", notes = "我的权益道具(任务中心-我的奖励)", httpMethod = "POST", produces = MediaType.APPLICATION_JSON_VALUE)
    @PostMapping(value = "/getMyEquity", produces = MediaType.APPLICATION_JSON_VALUE)
    @UserLogin
    public PageResult<UserEquityPropsVO> getMyEquity(@Valid @RequestBody PageRequest request) {
        return PageResult.success(userEquityPropsService.getMyEquity(UserPool.getUser().getId(), request.getPageNo(), request.getPageSize()));
    }

    @ApiOperation(value = "我的权益道具（我的-明细）", notes = "我的权益道具(任务中心-我的奖励)", httpMethod = "POST", produces = MediaType.APPLICATION_JSON_VALUE)
    @PostMapping(value = "/getMyEquityDetail", produces = MediaType.APPLICATION_JSON_VALUE)
    @UserLogin
    public PageResult<UserEquityPropsDetailVO> getMyEquityDetail(@RequestBody UserEquityPropsDetailRequest request) {
        return PageResult.success(userEquityPropsService.getMyEquityDetail(UserPool.getUser().getId(), request.getId(), request.getIsExpired(), request.toMp(), request.getIsGift()));
    }


    @ApiOperation(value = "是否持有某种道具卡", notes = "是否持有某种道具卡", httpMethod = "POST", produces = MediaType.APPLICATION_JSON_VALUE)
    @PostMapping(value = "/getIsHoldEquityDetail", produces = MediaType.APPLICATION_JSON_VALUE)
    @UserLogin
    public Result<Boolean> getIsHoldEquityDetail(@RequestBody EquityPropsIdRequest request) {
        return Result.success(userEquityPropsService.getIsHoldEquityDetail(UserPool.getUser().getId(), request.getEquityPropsId()));
    }

    @ApiOperation(value = "转赠损耗计算", notes = "转赠损耗计算", httpMethod = "POST", produces = MediaType.APPLICATION_JSON_VALUE)
    @PostMapping(value = "/incrementalLossCalculation", produces = MediaType.APPLICATION_JSON_VALUE)
    @UserLogin
    public Result<List<IncrementalLossCalculationVO>> incrementalLossCalculation(@Valid @RequestBody IncrementalLossCalculationDTO incrementalLossCalculationDTO) {
        return Result.success(userEquityPropsService.incrementalLossCalculation(incrementalLossCalculationDTO,UserPool.getUser()));
    }


    @ApiOperation(value = "通过用户链获取用户头像", notes = "通过用户链获取用户头像", httpMethod = "POST", produces = MediaType.APPLICATION_JSON_VALUE)
    @PostMapping(value = "/addressUserInfo", produces = MediaType.APPLICATION_JSON_VALUE)
    @UserLogin
    public Result<AddressUserInfoVO> addressUserInfo(@Valid @RequestBody AddressUserInfoDTO addressUserInfoDTO) {
        UserInfo user = UserPool.getUser();
        if (!user.getIsValid()) {
            throw new GlobalRunTimeException("无效用户,无转赠条件");
        }
        return Result.success(userEquityPropsService.addressUserInfo(addressUserInfoDTO,user));
    }


    @ApiOperation(value = "赠送", notes = "赠送", httpMethod = "POST", produces = MediaType.APPLICATION_JSON_VALUE)
    @PostMapping(value = "/gift", produces = MediaType.APPLICATION_JSON_VALUE)
    @UserLogin
    public Result gift(@Valid @RequestBody GiftDTO giftDTO) {
        List<RLock>locks=new ArrayList<>();
        GiftCT giftCT=new GiftCT();
        BeanUtil.copyProperties(giftDTO,giftCT);
        giftCT.setUserInfo(UserPool.getUser());
        List<Long> giftId = giftDTO.getGiftId();
        try{
            for (Long l : giftId) {
                String key=StrUtil.format("{}:{}", RedisKeyEnum.ITEM_CARD_GIFT.getKey(),l);
                RLock lock = redisson.getLock(key);
                locks.add(lock);
                boolean res = lock.tryLock(10, TimeUnit.SECONDS);
                if (!res) {
                    return Result.fail("请勿重复提交");
                }
            }
            userEquityPropsService.gift(giftCT);
        }catch (InterruptedException e) {
            return Result.fail("赠送失败");
        }finally {
            locks.forEach(rLock -> {
                if (rLock.isLocked()) {
                    rLock.unlock();
                }
            });
        }
        return Result.success();
    }

    @ApiOperation(value = "最新寄售信息", notes = "最新寄售信息", httpMethod = "POST", produces = MediaType.APPLICATION_JSON_VALUE)
    @PostMapping(value = "/getLastConsignDetails", produces = MediaType.APPLICATION_JSON_VALUE)
    @UserLogin
    public Result<EquityPropsLastConsignDetailsVO> getLastConsignDetails(@Valid @RequestBody EquityPropsIdRequest request) {
        return Result.success(userEquityPropsService.getLastConsignDetails(request.getEquityPropsId()));
    }
    //可寄售权益道具列表
    @ApiOperation(value = "用户可寄售权益道具列表", notes = "最新寄售信息", httpMethod = "POST", produces = MediaType.APPLICATION_JSON_VALUE)
    @PostMapping(value = "/getUserConsignEquityPropsPage", produces = MediaType.APPLICATION_JSON_VALUE)
    @UserLogin
    public PageResult<UserConsignEquityPropsPageVO> getUserConsignEquityPropsPage(@Valid @RequestBody UserConsignEquityPropsPageRequest request) {
        return PageResult.success(userEquityPropsService.getUserConsignEquityPropsPage(request.getEquityPropsId(),UserPool.getUser(),request.toMp()));
    }


    @ApiOperation(value = "寄售计价", notes = "寄售计价", httpMethod = "POST", produces = MediaType.APPLICATION_JSON_VALUE)
    @PostMapping(value = "/getUserConsignRealPrice", produces = MediaType.APPLICATION_JSON_VALUE)
    @UserLogin
    public Result<RealAmountVO> getUserRealPrice(@Valid @RequestBody UserConsignRealPriceRequest request) {
        return Result.success(userEquityPropsService.getUserRealPrice(UserPool.getUser(),request.getEquityPropsId(),request.getUserEquityPropsIds(),request.getConsignPrice()));
    }

    @ApiOperation(value = "寄售权益道具", notes = "寄售权益道具", httpMethod = "POST", produces = MediaType.APPLICATION_JSON_VALUE)
    @PostMapping(value = "/consignEquityProps", produces = MediaType.APPLICATION_JSON_VALUE)
    @UserLogin
    public Result consignEquityProps(@Valid @RequestBody ConsignEquityPropsRealPriceRequest request) {
        UserInfo user = UserPool.getUser();
        if (!UserPool.getUser().getTransactionPassword().equals(request.getDealPwd())) {
            throw new GlobalRunTimeException("支付密码错误");
        }


        Lock lock = redisson.getLock(RedisKeyEnum.CONSIGN_EQUITY_PROPS.getKey() + user.getId());
        try {
            boolean res = lock.tryLock(10,  TimeUnit.SECONDS);
            if (!res) {
                return Result.fail(ErrorCode.LATER_TRY);
            }
            userEquityPropsService.consignEquityProps(UserPool.getUser(),request.getEquityPropsId(),request.getUserEquityPropsIds(),request.getConsignPrice());
        } catch (InterruptedException e) {
            log.error(StrUtil.format("寄售权益道具异常:{}",e));
            return Result.fail(ErrorCode.LATER_TRY);
        } finally {
            lock.unlock();
        }

        return Result.success();
    }

    @ApiOperation(value = "我的挂单", notes = "我的挂单", httpMethod = "POST", produces = MediaType.APPLICATION_JSON_VALUE)
    @PostMapping(value = "/myConsignEquityPropsPage", produces = MediaType.APPLICATION_JSON_VALUE)
    @UserLogin
    public PageResult<MyConsignEquityPropsPageVO> myConsignEquityPropsPage(@Valid @RequestBody MyConsignEquityPropsPageRequest request) {
        return PageResult.success(secondEquityPropsService.myConsignEquityPropsPage(UserPool.getUser(),request.toMp(),request.getType()));
    }


    @ApiOperation(value = "批量下架", notes = "撤销挂单", httpMethod = "POST", produces = MediaType.APPLICATION_JSON_VALUE)
    @PostMapping(value = "/cancelConsignEquityProps", produces = MediaType.APPLICATION_JSON_VALUE)
    @UserLogin
    public Result cancelConsignEquityProps(@Valid @RequestBody CancelConsignEquityPropsRequest request) {
        UserInfo user = UserPool.getUser();
        if (!user.getTransactionPassword().equals(request.getDealPwd())) {
            throw new GlobalRunTimeException("支付密码错误");
        }

        secondEquityPropsService.batchCancelConsignEquityProps(UserPool.getUser(),request.getSecondProductIds());
        return Result.success();
    }

}
